package com.zx.mes.longsecurity.hyl.service.impl;

import com.zx.mes.hyl.common.pagemodel.LayPageHelper;
import com.zx.mes.hyl.common.pagemodel.SessionInfo;
import com.zx.mes.hyl.common.pagemodel.Tree;

import com.zx.mes.longsecurity.hyl.dao.ResourceRepository;
import com.zx.mes.longsecurity.hyl.dao.RoleRepository;
import com.zx.mes.longsecurity.hyl.dao.UserRepository;
import com.zx.mes.longsecurity.hyl.domain.Tresource;
import com.zx.mes.longsecurity.hyl.domain.Trole;
import com.zx.mes.longsecurity.hyl.domain.Tuser;
import com.zx.mes.longsecurity.hyl.pagemodel.Role;
import com.zx.mes.longsecurity.hyl.service.RoleServiceI;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author hyl
 */
@Service
public class RoleServiceImpl implements RoleServiceI {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private ResourceRepository resourceRepository;


    @Override
    public void add(Role role) throws Exception{

        Trole trole=roleRepository.findByName(role.getName());

        if (trole !=null && "".equals(trole.getId())){
            throw new Exception("角色名已存在！");
        }else{
            Trole t = new Trole();
            BeanUtils.copyProperties(role, t);
            if (role.getPid()!=null &&! "".equalsIgnoreCase(role.getPid())){
                t.setTrole(roleRepository.getOne(role.getPid()));
            }
            roleRepository.save(t);
        }

    }

    @Override
    public Role get(String id) {

        Role r = new Role();
        Trole t=roleRepository.getById(id);

        if (t != null) {
            BeanUtils.copyProperties(t, r);
            if (t.getTrole() != null) {
                r.setPid(t.getTrole().getId());
                r.setPname(t.getTrole().getName());
            }
            Set<Tresource> s = t.getTresources();
            getChildren(r, s);
        }
        return r;
    }

    @Override
    public void edit(Role role) throws Exception {

        List<Trole> list=roleRepository.getAllByName(role.getName());

        if (list !=null && list.size()>1){
            throw new Exception("角色名已存在");
        }else{

            if (role.getPid()!=null && !"".equalsIgnoreCase(role.getPid())){
                roleRepository.updateById2(role.getName(),role.getRemark(),role.getAlias(),roleRepository.getOne(role.getPid()),role.getId());
            }else{
                roleRepository.updateById(role.getName(),role.getRemark(),role.getAlias(),role.getId());

            }

        }
    }

    @Override
    public List<Role> treeGrid(SessionInfo sessionInfo) {
        List<Role> rl = new ArrayList<>();
        List<Trole> tl ;

        tl=roleRepository.findByUserId(sessionInfo.getId());
        listReturn(rl, tl);
        return rl;
    }

    @Override
    public List<Role> getRoles(String userId) {
        List<Role> rl = new ArrayList<>();
        List<Trole> tl ;

        tl=roleRepository.findByUserId(userId);
        if (tl != null && tl.size() > 0) {
            for (Trole t : tl) {
                Role r = new Role();
                BeanUtils.copyProperties(t, r);
                if (t.getTrole() != null) {
                    r.setPid(t.getTrole().getId());
                    r.setPname(t.getTrole().getName());
                }
                rl.add(r);
            }
        }
        return rl;
    }

    @Override
    public void delete(String id) {
        Trole t = roleRepository.getOne(id);
        del(t);
    }

    private void del(Trole t) {
        if (t.getTroles() != null && t.getTroles().size() > 0) {
            for (Trole r : t.getTroles()) {
                del(r);
            }
        }
        roleRepository.delete(t);
    }

    @Override
    public List<Tree> tree(Tuser tuser) {
        List<Trole> l ;
        List<Trole> LL ;
        List<Tree> lt = new ArrayList<>();


        LL = roleRepository.findAllRoleByUserId(tuser.getId());

        l = roleRepository.findAll();



        if (l != null && l.size() > 0) {
            for (Trole t : l) {
                Tree tree = new Tree();
                BeanUtils.copyProperties(t, tree);
                tree.setText(t.getName());
                tree.setName(t.getAlias());
                tree.setIconCls("status_online");
                if (t.getTrole() != null) {
                    tree.setPid(t.getTrole().getId());
                }

                for (int i=0;i<LL.size();i++){
                    if (t.getId()==LL.get(i).getId()){
                        tree.setChecked(true);
                        //跳出内层for
                        break;
                    }
                }
                lt.add(tree);
            }
        }
        return lt;
    }

    @Override
    public List<Tree> allTree(Tuser tuser) {
        return this.tree(tuser);
    }

    @Override
    public List<Tree> getAll() {
        List<Trole> l ;
        List<Tree> lt = new ArrayList<>();

        l = roleRepository.findAll();


        if (l != null && l.size() > 0) {
            for (Trole t : l) {
                Tree tree = new Tree();
                BeanUtils.copyProperties(t, tree);
                tree.setText(t.getName());
                tree.setName(t.getAlias());
                tree.setIconCls("status_online");
                if (t.getTrole() != null) {
                    tree.setPid(t.getTrole().getId());
                }

                lt.add(tree);
            }
        }
        return lt;
    }

    @Override
    public void grant(Role role) {
        Trole t = roleRepository.getOne(role.getId());
        if (role.getResourceIds() != null && !"".equalsIgnoreCase(role.getResourceIds())) {

            List<String> ids=new ArrayList<>();
            for (String id : role.getResourceIds().split(",")) {
                ids.add(id);
            }
            t.setTresources(new HashSet<Tresource>(resourceRepository.findAll(ids)));
            t.setTresources(null);
        }
    }

    @Override
    public List<Role> findAll(Role role, LayPageHelper ph) {
        List<Role> listReturn = new ArrayList<>();
        List<Trole> tresourceList;
        Pageable pageable=new PageRequest(ph.getPage()-1, ph.getLimit());
        if (role !=null && null==role.getName()){
            tresourceList =roleRepository.findAll(pageable).getContent();
        }else{
            tresourceList =roleRepository.findByNameLike("%"+role.getName()+"%",pageable);
        }


        listReturn(listReturn, tresourceList);
        return listReturn;
    }

    private void listReturn(List<Role> listReturn, List<Trole> tresourceList) {
        if (tresourceList != null && tresourceList.size() > 0) {
            for (Trole t : tresourceList) {
                Role r = new Role();
                BeanUtils.copyProperties(t, r);
                r.setIconCls("status_online");
                if (t.getTrole() != null) {
                    r.setPid(t.getTrole().getId());
                    r.setPname(t.getTrole().getName());
                }
                Set<Tresource> s = t.getTresources();
                getChildren(r, s);
                listReturn.add(r);
            }
        }
    }

    private void getChildren(Role r, Set<Tresource> s) {
        if (s != null && !s.isEmpty()) {
            boolean b = false;
            String ids = "";
            String names = "";
            for (Tresource tr : s) {
                if (b) {
                    ids += ",";
                    names += ",";
                } else {
                    b = true;
                }
                ids += tr.getId();
                names += tr.getName();
            }
            r.setResourceIds(ids);
            r.setResourceNames(names);
        }
    }

    @Override
    public long count(Role role) {
        return roleRepository.count(getSpec(role));
    }


    private Specification<Trole> getSpec(Role role) {
        return new Specification<Trole>() {
            @Override
            public Predicate toPredicate(Root<Trole> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicateList=new ArrayList<>();
                if (role.getName()!=null && ! "".equalsIgnoreCase(role.getName())){
                    predicateList.add(cb.like(root.get("name").as(String.class),"%"+role.getName()+"%"));
                }

                query.where(predicateList.toArray(new Predicate[predicateList.size()]));
                return null;
            }
        };
    }
}
